package org.example;


import org.example.bean.ParseTable;
import org.example.bean.Production;
import org.example.bean.VN;
import org.example.bean.VT;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;

public class GrammarParser {
    public List<Production> productions;
    public Map<String,Production> productionMap;//不会发生在Set查不到元素，并且为first计算做准备
    public GrammarParser(){};
    static String start="";
    public static void main(String[] args) {
        File grammarFile = new File("src/main/resources/grammar2.txt"); // 替换为实际的文法文件路径

        try {
            List<Production> productions = parseGrammar(grammarFile);
            for (Production production : productions) {
                System.out.println(production);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }



    public static List<Production> parseGrammar(File grammarFile) throws FileNotFoundException {
        Map<String,Set<List<String>>> productions = new HashMap<>();
        Scanner scanner = new Scanner(grammarFile);
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            String[] parts = line.split("::=");

            String left = parts[0].trim();
            String right = parts.length > 1 ? parts[1].trim() : "";
            if(right.isEmpty()){
                right="ε";
            };
            String[] split = right.split(" ");
            List<String> r= new ArrayList<>();
            for (String s : split) {
                r.add(s.trim());
            };
            Set<List<String>> set=new HashSet<>();
            set.add(r);
            if(start.isEmpty()){
                start=left;
            }
            if(productions.get(left)!=null) {
                productions.get(left).addAll(set);
            }
            else {
                productions.put(left,set);
            }
        };


        scanner.close();
        //遍历productions将其转换为List集合
        List<Production> productionList = new ArrayList<>();
        for (Map.Entry<String, Set<List<String>>> pairs: productions.entrySet()) {
            String left = pairs.getKey();
            productionList.add(new Production(left, pairs.getValue()));
        };

        return productionList;
    }


    public static void eliminateLeftRecursion(List<Production> productions) {
        Production production2 = productions.get(0);
        productions.remove(0);
        productions.add((production2));


        Set<Production> new_pros = new HashSet<>();
        Map<String,Set<List<String>>> newPros=new HashMap<>();//左部映射右部的产生式表示
        for (Production production : productions) {
            /**
             * 消除间接左递归
             */

            for (Production production1 : productions) {
                if (production1 == production) break;

                List<List<String>> add = new ArrayList<>();
                List<String> del = new ArrayList<>();
                for (List<String> strings : production.getRight()) {

                    if (strings.get(0).equals(production1.getLeft())) {

                        del = strings;

                        for (List<String> stringList : production1.getRight()) {
                            List<String> tmp = new ArrayList<>(strings);
                            tmp.remove(0);
                            tmp.addAll(0, stringList);
                            add.add(tmp);
                        }
                        ;
                    }
                    ;
                }
                ;
                Set<List<String>> right = production.getRight();
                right.remove(del);
                right.addAll(add);
                production.right=right;
            };

            /**
             * 消除直接左递归
             * 1.预处理
             * 2.
             */
            List<List<String>> VTSet = new ArrayList<>();
            for (List<String> strings : production.getRight()) {
                if(!strings.get(0).equals(production.getLeft())){
                    List<String> newRight=new ArrayList<String>(strings);
//                    newRight.add(production.getLeft()+"'");
                    VTSet.add(newRight);
                }
            };

            List<List<String>> add=new ArrayList<>();//新的右部
            List<List<String>> del=new ArrayList<>();//要删除的递归式
            for (List<String> strings : production.getRight()) {
                if(strings.get(0).equals(production.getLeft())){
                    //消除第一个
                    //删除原左部递归式
                    del.add(strings);
                    //添加新右部TE'
                    if(add.isEmpty()) {
                        for (List<String> stringList : VTSet) {
                            List<String> strings1 = new ArrayList<>(stringList);


                            strings1.add(production.getLeft()+"'");
                            add.add(strings1);
                            del.add(stringList);
                        };
                    }
                    //构造新的产生式E'->+TE'
                    strings.remove(0);
                    strings.add(production.getLeft()+"'");
                    if(newPros.containsKey(production.getLeft()+"'")){
                        newPros.get(production.getLeft()+"'").add(strings);
                    }
                    else {
                        Set<List<String>> set = new HashSet<>();
                        set.add(strings);
                        newPros.put(production.getLeft() + "'", set);
                    }

                    //新的产生式添加空
                    List<String> str=new ArrayList<>();
                    str.add("ε");
                    newPros.get(production.getLeft()+"'").add(str);
                };
            };
            //正式添加新右部
            Set<List<String>> r=new HashSet<>(production.getRight());
            production.setRight(r);
            production.right.addAll(add);
            //删除旧左部
            HashSet<List<String>> lists = new HashSet<>();
            r=new HashSet<>(production.getRight());
            production.setRight(r);
            for (List<String> strings : del) {
                production.getRight().remove(strings);
            }

        };
        newPros.forEach((k,v)-> productions.add(new Production(k,v)));
        for (Production production : productions) {
            System.out.println(production);
        }
        }

    public  void getAllFirst(List<Production> productions){
        preGetFist(productions);
        for (Production production : productions) {
            production.first=getFirst(production);
            System.out.println("First["+production.getLeft()+"]:"+production.first);
        }
    }
    public void getAllFollow(List<Production> productions){
        for (Production production : productions) {
            production.follow=getFollow(production);
            System.out.println("Follow["+production.getLeft()+"]:"+production.follow);
        }

    }

    private List<String> getFollow(Production production) {
        if(production.follow!=null)return production.follow;
        Set<String> res=new HashSet<>();
        for (Production production1 : productions) {
            for (List<String> oneRight : production1.getRight()) {
                //找到包含这个文法符号的其它产生式
                int idx=0;
                if(oneRight.indexOf(production.getLeft())!=oneRight.size()-1){
                    for (String s : oneRight) {
                        if(idx>oneRight.indexOf(production.getLeft())) {
                            if (VN.isVN(s)) {
                                //计算文法符号的后面的文法符号的first
                                List<String> tmp = new ArrayList<>(getFirst(productionMap.get(s)));
                                if (!tmp.contains("ε")) {
                                    break;
                                }
                            }
                            else if(VT.isVT(s)){
                                res.add(s);
                                break;
                            }
                        }
                        idx++;
                    }
                }
            }
        };
        return new ArrayList<>(res);
    }

    private  void preGetFist(List<Production> productions) {
        this.productions=productions;
        productionMap=new HashMap<>();
        productions.forEach(x->{
            productionMap.put(x.left,x);
        });
    }

    public  List<String> getFirst(Production production) {
        if (production.first != null) return production.first;
        //遍历每一个产生式右部
        List<String> res=new ArrayList<>();
        for (List<String> oneRight : production.getRight()) {
            int len=oneRight.size();
            int idx=0;
            //遍历每一个产生式右部序列
            for (String idxS : oneRight) {
                //终结符直接加入first
                if (VT.isVT(idxS)) {

                    res.add(idxS);
                    if(idxS.equals("ε")&&idx!=len-1){
                        res.remove(idxS);
                    }
                    break;
                }
                //非终结符递归计算first
                else if(VN.isVN(idxS)){
                    Set<List<String>> right = productionMap.get(idxS).getRight();
                    res.addAll(getFirst(productionMap.get(idxS)));
                    int haveNull=0;
                    for (List<String> strings : right) {
                        if(strings.size()==1&&strings.get(0).equals("ε")){
                            haveNull=1;
                        }
                    }
                    //还得判断是否含有空
                    if(haveNull==0){
                        break;
                    }
                };
                idx++;
            }
        };
        return res;
    }

    ParseTable parseTable;
    public ParseTable initParseTable(List<Production> productions){
        ParseTable table=new ParseTable();
        for (Production production : productions) {
            for (List<String> strings : production.right) {
                int flag=0;
                if(productionMap.containsKey(strings.get(0))){
                    Production pro = productionMap.get(strings.get(0));
                    for (String s : pro.first) {
                        if(s.equals("null"))flag=1;
                        table.left=production.left;
                        table.right.addAll(strings);
                        table.vt=s;
                    };
                    if(flag==0){
                        break;
                    }
                    else{//包含空使用follow
                        for (String s : pro.follow) {
                            table.left=production.left;
                            table.right.addAll(strings);
                            table.vt=s;
                        }
                    }
                }
            }
        };
        return table;
    };
    /*


    public  List<String> getFirst(Production production){
            if(production.first!=null)return production.first;

        for (List<String> oneRight : production.getRight()) {
            for (String idxS : oneRight) {
                if (VT.isVT(idxS)){


//                if (!oneRight.isEmpty()) {
//                    if (VT.isVT(oneRight.get(0)))
//                        production.first.add(oneRight.get(0));
//                    else if (VN.isVN(oneRight.get(0))) {//寻找非终结符开头
//                        for (Production production1 : productions) {
//                            if (production1.getLeft().equals(productions.oneRight.get(0))) {//遍历找到这个产生式
//                                List<String> tmp = getFirst(production1);//递归计算
//                                production.first.addAll(tmp);//添加到结果中
//                                //遍历这个产生式的右部是否含有空，有则计算下一个产生式
//                                for (List<String> strings : production1.getRight()) {
//                                    if (!strings.isEmpty()) {
//                                        //含有空
//                                        if (strings.get(0).equals("ε")) {
//                                            //遍历剩下的产生式，但是这会重复添加，更好的办法是整个函数是一个二层循环，第二层遍历每一个产生式右部的序列，这待优化
//                                            for (String s : oneRight) {
//                                                for (Production production2 : productions) {
////                                                找到终结符
//                                                    if (production2.getLeft().equals(s)) {
//                                                        tmp = getFirst(production2);//递归计算
//                                                        if (production.first.contains(tmp))
//                                                            production.first.addAll(tmp);
//                                                    }
//                                                }
//                                            }
//                                            break;
//                                        }
//                                    }
//                                }
//                                ;
//
//                                break;
//                            }
//                        }
//                        ;

                    }
                }
            }
        }
    }
     */
}
